﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WinFormLogger.Logging
{
    public class FileLogger : IlogHandler, IDisposable
    {

        /// <summary>
        /// 日志文件路径
        /// </summary>
        private string LogFilePath { get; set; }

        /// <summary>
        /// 写入器
        /// </summary>
        private StreamWriter streamWriter;

        /// <summary>
        /// 文件流
        /// </summary>
        private FileStream fileStream;

        /// <summary>
        /// 日志目录
        /// </summary>
        private string _logDirectory;

        /// <summary>
        /// 日志文件名
        /// </summary>
        private readonly string _filePrefix;

        /// <summary>
        /// 日志后缀名
        /// </summary>
        private readonly string _fileExtension;

        /// <summary>
        /// 是否自动刷新
        /// </summary>
        private bool AutoFlush { get; set; } = true;

        /// <summary>
        /// 最小日志级别
        /// </summary>
        private LogLevel MinLevel { get; set; } = LogLevel.Debug;

        /// <summary>
        /// 是否使用每日日志
        /// </summary>
        private bool UseDailyFile { get; set; } = true;

        /// <summary>
        /// 日志时间
        /// </summary>
        private DateTime _currentDate;

        private readonly object _lockWrite = new object();

        /// <summary>
        /// 创建文件日志处理器
        /// </summary>
        /// <param name="logfilePath">日志文件路径，如果为null则创建Logs目录</param>
        /// <param name="autoFlush">是否自动刷新</param>
        /// <param name="logLevel">日志级别</param>
        /// <param name="useDailyFile">是否使用每日日志文件</param>
        public FileLogger(string logfilePath = null,bool autoFlush =true,LogLevel logLevel = LogLevel.Debug,bool useDailyFile = true)
        {
            AutoFlush = autoFlush;
            MinLevel = logLevel;
            UseDailyFile = useDailyFile;
            _currentDate = DateTime.Today;

            if (string.IsNullOrEmpty(logfilePath))
            {
                string fileDic = AppDomain.CurrentDomain.BaseDirectory;
                _logDirectory = Path.Combine(fileDic,"Logs");
                _filePrefix = "log";
                _fileExtension = "txt";
            }
            else
            {
                LogFilePath = logfilePath;
                _logDirectory = Path.GetDirectoryName(logfilePath);
                _filePrefix = Path.GetFileNameWithoutExtension(logfilePath);
                _fileExtension= Path.GetExtension(logfilePath);
            }

            if (!Directory.Exists(_logDirectory)) 
            {
                Directory.CreateDirectory(_logDirectory);
            }
            InitializeWrite();
        }
        private void InitializeWrite()
        {
            try
            {
                string filePath;
                if (UseDailyFile)
                {
                    //使用日期作为文件名的一部分
                    string dateTime = DateTime.Now.ToString("yyyyMMdd");
                    filePath = LogFilePath;
                }
                else
                {
                    filePath = Path.Combine(_logDirectory,$"{_filePrefix}{_fileExtension}");
                }
                LogFilePath = filePath;

                //打开文件流，如果存在则追加
                
                fileStream =new FileStream(filePath,FileMode.Append,FileAccess.Write,FileShare.Read);
                
                streamWriter = new StreamWriter(fileStream, Encoding.UTF8);
                streamWriter.AutoFlush = AutoFlush;
                if (fileStream.Length == 0) 
                {
                    streamWriter.WriteLine($"=================日志开始{DateTime.Now:yyyy-MM-dd}================");
                    streamWriter.WriteLine();
                    if (AutoFlush) 
                    {
                        streamWriter.Flush();
                    }
                }
            }
            catch (Exception ex) 
            {
                Console.WriteLine($"初始化文件系统出错{ex.Message}");
            }
        }
        public void Dispose()
        {

        }

        public void ProcessLog(LogEventArgs logEvent)
        {
            if (logEvent.Level < MinLevel)
            {
                return;
            }
            lock (_lockWrite)
            {
                try
                {
                    //如果使用的每日日志文件但日期与现在不符合就创建新文件
                    if (UseDailyFile && _currentDate!=DateTime.Today) 
                    {
                        //关闭当前文件
                        CloseWriter();

                        //更新当前日期
                        _currentDate = DateTime.Today;

                        InitializeWrite();
                    }

                    //写入日志内容
                    string time = $"{logEvent.DateTime:yyyy-MM-dd:HH:mm:ss}";
                    string level = $"{logEvent.Level}";
                    string message = logEvent.Message;
                    string source =$"[{logEvent.Source}]";

                    streamWriter.WriteLine($"{time}{level}{source}{message}");

                    if (AutoFlush) 
                    {
                        streamWriter.Flush();
                    }
                }
                catch (Exception ex) 
                {
                    Console.WriteLine($"写入日志文件出错{ex.Message}");
                }
            }
        }

        private void CloseWriter() 
        {
            try
            {
                if (streamWriter != null) 
                {
                    streamWriter.WriteLine();
                    streamWriter.WriteLine($"=================日志结束{DateTime.Now:yyyy-MM-dd}================");
                    streamWriter.Close();
                    streamWriter.Flush();
                    streamWriter.Dispose();
                }

                if (fileStream != null) 
                {
                    fileStream.Dispose();
                    fileStream = null;
                }
            }
            catch (Exception ex) 
            {
                Console.WriteLine($"关闭文件错误{ex.Message}");
            }
            
        }
    }
}
